<template>
  <div class="cx-form-container">
    <div class="form-body" :class="{ 'board-bg': displayBoardBg }">
      <el-form
        ref="form"
        label-position="right"
        :model="internalAttMap"
        :rules="formRules"
        :inline="colNum > 1"
        :size="size"
      >
        <!-- 字段分组渲染 -->
        <template v-for="(groupFlds, groupName) in fldGroups" :key="groupName">
          <!-- 分组标题 -->
          <div v-if="shouldShowGroupTitle(groupName, groupFlds)" class="field-group-title">
            <div class="group-indicator"></div>
            <span class="group-name">{{ groupName }}</span>
          </div>

          <!-- 字段渲染 -->
          <template v-for="fld in getVisibleFields(groupFlds)" :key="fld.colname">
            <!-- 自定义字段组件 -->
            <component
              v-if="getCustomComponent(fld)"
              :is="getCustomComponent(fld)"
              :fld="fld"
              :attMap="internalAttMap"
              :mode="internalMode"
              :state="this"
            />

            <!-- 默认字段渲染 -->
            <div v-else class="field-item" :class="getFieldItemClass(fld)">
              <!-- 字段自定义渲染插槽 -->
              <slot name="fld" :fld="fld" :controller="fileController">
                <!-- 字段自定义组件 -->
                <component
                  v-if="fld.component"
                  :is="fld.component"
                  :fld="fld"
                  :mode="internalMode"
                  :disabled="!isFieldEnabled(fld)"
                  :portrait="getFieldPortrait(fld)"
                  :hint="getFieldHint(fld)"
                  @change="onFldChange"
                  @file-data="onFileData"
                  @val-button="onValButton"
                />

                <!-- 标准字段组件 -->
                <Fld
                  v-else
                  :fld="fld"
                  :mode="internalMode"
                  :disabled="!isFieldEnabled(fld)"
                  :portrait="getFieldPortrait(fld)"
                  :hint="getFieldHint(fld)"
                  :size="size"
                  @fld-change="onFldChange"
                  @val-button="onValButton"
                >
                  <template #label>
                    <slot name="label" :fld="fld"></slot>
                  </template>
                  <template #value>
                    <slot name="value" :fld="fld"></slot>
                  </template>
                </Fld>
              </slot>

              <!-- 字段插入组件插槽 -->
              <slot name="field-append" :fld="fld" :formData="internalAttMap" :mode="internalMode">
                <component v-if="getInsertWidget(fld)" :is="getInsertWidget(fld)" :fld="fld" />
              </slot>
            </div>
          </template>
        </template>

        <!-- 多媒体组件区域 -->
        <div v-if="hasMediaComponents" class="media-components">
          <!-- 照片上传组件 -->
          <div v-if="showPhoto" class="photo-widget">
            <slot name="photo" :controller="fileController">
              <div class="media-title">照片</div>
              <Photo
                :editable="internalMode !== 6"
                :controller="fileController"
                :busType="fileController?.busType || '0'"
                :showDownLoadBtn="showDownLoadBtn"
                :isCompress="isCompress || false"
                @photo-selected="onPhotoSelected"
                @photo-deleted="onPhotoDeleted"
                @upload-complete="onPhotoUploadComplete"
              />
            </slot>
          </div>

          <!-- 视频上传组件 -->
          <div v-if="showVideo" class="video-widget">
            <slot name="video" :controller="fileController">
              <div class="media-title">视频</div>
              <Video
                :editable="internalMode !== 6"
                :controller="fileController"
                :busType="fileController?.busType || '0'"
                :maxDuration="maxDuration || 300"
                :isCompress="isCompress || false"
                :saveGallery="saveGallery || false"
                @video-selected="onVideoSelected"
                @video-deleted="onVideoDeleted"
                @upload-complete="onVideoUploadComplete"
              />
            </slot>
          </div>

          <!-- 附件上传组件 -->
          <div v-if="showAttach" class="attach-widget">
            <slot name="attach" :controller="fileController">
              <div class="media-title">附件</div>
              <Attach
                :editable="internalMode !== 6"
                :controller="fileController"
                :busType="fileController?.busType || '0'"
                :showDownLoadBtn="showDownLoadBtn"
                @attach-selected="onAttachSelected"
                @attach-deleted="onAttachDeleted"
                @upload-complete="onAttachUploadComplete"
              />
            </slot>
          </div>
        </div>

        <!-- 底部自定义组件区域 -->
        <slot name="bottom" :formData="internalAttMap" :mode="internalMode" :controller="this">
          <div v-if="bottomDiyView.length > 0" class="bottom-widgets">
            <component v-for="(widget, index) in bottomDiyView" :key="index" :is="widget" />
          </div>
        </slot>
      </el-form>
    </div>

    <!-- 加载状态遮罩 -->
    <div v-if="isLoading" class="loading-overlay" v-loading="isLoading" :element-loading-text="loadingMessage">
    </div>
  </div>
</template>

<script>
/**
 * 组件名称: Form (Element UI 版本)
 * 功能说明: 属性表单组件，支持动态字段渲染、多列布局、表单验证、多媒体组件等功能
 * 研发时间: 2025/11/17
 * 研发人员: AI Assistant
 * 
 * 基于 cx2-form 改造为 Element UI 版本，适配桌面端
 */

import props from './props'
import Fld from '../Fld.vue'
import Photo from '../Photo.vue'
import Video from '../Video.vue'
import Attach from '../Attach.vue'
import initialization from './mixins/Initialization'
import fieldControl from './mixins/FieldControl'
import formValidation from './mixins/FormValidation'
import formSubmission from './mixins/FormSubmission'
import configLoader from './mixins/ConfigLoader'
import eventHandlers from './mixins/EventHandlers'
import apiCalls from './mixins/ApiCalls'

export default {
  name: 'Form',

  components: {
    Fld,
    Photo,
    Video,
    Attach
  },
  
  mixins: [
    props,
    initialization,
    fieldControl,
    formValidation,
    formSubmission,
    configLoader,
    eventHandlers,
    apiCalls
  ],

  data() {
    return {
      /** 表单状态[7-添加，5-修改，6-查询] */
      internalMode: null,

      /** 内部表单数据 */
      internalAttMap: {},

      /** 实体对象 */
      internalEntity: {},

      /** 字段列表 */
      internalFldList: [],

      /** 字段值映射 */
      fldValueMap: {},

      /** 规则表列表 */
      ruleTabList: [],

      /** 正在编辑的字段名 */
      editingColName: null,

      /** 缓存策略实例 */
      internalAttMapStrategy: null,

      /** 文件控制器实例 */
      internalFileController: null,

      /** 是否正在提交 */
      isSubmitting: false,

      /** 是否正在加载 */
      isLoading: false,

      /** 加载消息 */
      loadingMessage: '',

      /** 表单验证规则 */
      formRules: {},

      /** 编码规则 */
      codeRule: null,

      /** 验证器映射表 */
      validatorMap: {},

      /** RuleTab规则校验的时机 */
      ruleTabCheckTime: {
        new: 1,        // 表单新建状态初始化时，即[ADD]
        edit: 2,       // 已有表单编辑状态初始化时,即[MODIFY]
        change: 3,     // 某个字段数据被修改后
        commit: 4,     // 新增数据提交之前
        editCommit: 5  // 编辑数据提交
      }
    }
  },

  computed: {
    /**
     * 字段分组
     */
    fldGroups() {
      const groups = {}

      for (const fld of this.internalFldList) {
        const groupName = fld.params?.grpc || fld.colname

        if (!groups[groupName]) {
          groups[groupName] = []
        }

        groups[groupName].push(fld)
      }

      return groups
    },

    /**
     * 是否有多媒体组件
     */
    hasMediaComponents() {
      return this.showPhoto || this.showVideo || this.showAttach
    },

    /**
     * 文件控制器
     */
    fileController() {
      return this.internalFileController || this.createDefaultFileController()
    },

    /**
     * 缓存策略实例
     */
    attMapStrategyHandler() {
      return this.internalAttMapStrategy || this.createDefaultAttMapStrategy()
    }
  },

  watch: {
    /**
     * 监听mode变化
     */
    mode: {
      handler(newVal) {
        this.internalMode = this.validateMode(newVal)
      },
      immediate: true
    },

    /**
     * 监听attMap变化
     */
    attMap: {
      handler(newVal) {
        if (newVal && typeof newVal === 'object') {
          this.internalAttMap = { ...newVal }
          this.checkAndQueryById(this.internalAttMap)
        }
      },
      immediate: true,
      deep: true
    },

    /**
     * 监听internalAttMap变化，同步更新字段值
     */
    internalAttMap: {
      handler(newVal) {
        this.syncFieldValues(newVal)
      },
      deep: true
    },

    /**
     * 监听fldList变化
     */
    fldList: {
      handler(newVal) {
        if (Array.isArray(newVal)) {
          this.internalFldList = [...newVal]
          this.$nextTick(() => {
            this.initializeFieldValues()
          })
        }
      },
      immediate: true
    },

    /**
     * 监听tabCfgName变化
     */
    tabCfgName: {
      handler(newVal) {
        if (newVal && this.enableTabCfg) {
          this.loadFromTabCfg(newVal)
        }
      },
      immediate: true
    },

    /**
     * 监听tempUrl变化
     */
    tempUrl: {
      handler(newVal) {
        if (newVal) {
          this.loadFromTemplate(newVal)
        }
      },
      immediate: true
    }
  },

  async created() {
    await this.initializeComponent()
  },

  methods: {
    /**
     * 照片选中事件处理
     */
    onPhotoSelected(photo) {
      this.$emit('photo-selected', photo)
    },

    /**
     * 照片删除事件处理
     */
    onPhotoDeleted(photo) {
      this.$emit('photo-deleted', photo)
      this.handleFieldChange()
    },

    /**
     * 照片上传完成事件处理
     */
    onPhotoUploadComplete(photo) {
      this.$emit('photo-upload-complete', photo)
      this.handleFieldChange()
    },

    /**
     * 视频选中事件处理
     */
    onVideoSelected(video) {
      this.$emit('video-selected', video)
    },

    /**
     * 视频删除事件处理
     */
    onVideoDeleted(video) {
      this.$emit('video-deleted', video)
      this.handleFieldChange()
    },

    /**
     * 视频上传完成事件处理
     */
    onVideoUploadComplete(video) {
      this.$emit('video-upload-complete', video)
      this.handleFieldChange()
    },

    /**
     * 附件选中事件处理
     */
    onAttachSelected(attach) {
      this.$emit('attach-selected', attach)
    },

    /**
     * 附件删除事件处理
     */
    onAttachDeleted(attach) {
      this.$emit('attach-deleted', attach)
      this.handleFieldChange()
    },

    /**
     * 附件上传完成事件处理
     */
    onAttachUploadComplete(attach) {
      this.$emit('attach-upload-complete', attach)
      this.handleFieldChange()
    },

    /**
     * 处理字段变化
     */
    handleFieldChange() {
      this.$emit('field-change', {
        formData: this.internalAttMap,
        mode: this.internalMode
      })
    }
  }
}
</script>

<style lang="scss" scoped>
.cx-form-container {
  position: relative;
  width: 100%;
  min-height: 100%;
}

.form-body {
  padding: 16px;
}

.form-body.board-bg {
  background-image: 
    linear-gradient(rgba(0, 0, 0, 0.05) 1px, transparent 1px),
    linear-gradient(90deg, rgba(0, 0, 0, 0.05) 1px, transparent 1px);
  background-size: 20px 20px;
}

.field-group-title {
  display: flex;
  align-items: center;
  width: 100%;
  margin: 16px 0 8px 0;
  padding: 8px;
  background-color: #fff;
  border-left: 4px solid #409eff;
}

.group-indicator {
  width: 4px;
  height: 16px;
  margin-right: 8px;
  background-color: #409eff;
  border-radius: 2px;
}

.group-name {
  font-size: 16px;
  font-weight: 600;
  color: #333;
}

.field-item {
  margin-bottom: 8px;
  transition: all 0.3s;
}

.field-item.field-disabled {
  opacity: 0.6;
}

.media-components {
  margin-top: 16px;
  padding: 16px;
  background-color: #fff;
  box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
  border-radius: 8px;
}

.media-title {
  margin-bottom: 12px;
  padding-bottom: 8px;
  border-bottom: 1px solid #e8e8e8;
  font-size: 16px;
  font-weight: 600;
  color: #333;
}

.photo-widget,
.video-widget,
.attach-widget {
  margin-bottom: 16px;
}

.photo-widget:last-child,
.video-widget:last-child,
.attach-widget:last-child {
  margin-bottom: 0;
}

.bottom-widgets {
  margin-top: 16px;
  padding: 16px;
  background-color: #fff;
  box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
  border-radius: 8px;
}

.loading-overlay {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  z-index: 1000;
  display: flex;
  flex-direction: column;
  justify-content: center;
  align-items: center;
  background-color: rgba(255, 255, 255, 0.8);
}
</style>
